package core;

import utils.Utils;
import networkrespnse.CallSignChangedResponse;
import networkrespnse.CancelEfirOrder;
import networkrespnse.ChangeState;
import networkrespnse.ClearEfir;
import networkrespnse.DriverMessageResponse;
import networkrespnse.DriverParkingPositionResponse;
import networkrespnse.GetCSBalanceAnswer;
import networkrespnse.GetOrdersResponse;
import networkrespnse.LoginResponse;
import networkrespnse.OrderResponse;
import networkrespnse.OrderResponse2;
import networkrespnse.OrderResponse3;
import networkrespnse.OrderResponse4;
import networkrespnse.PPCSettingsResponse;
import networkrespnse.ParseError;
import networkrespnse.PingResponse;
import networkrespnse.PreOrdersResponse;
import networkrespnse.RefusePreliminaryOrderAnswer;
import networkrespnse.RegisterOnTaxiParkingResponse;
import networkrespnse.RelayCommunicationResponse;
import networkrespnse.RequestConfirmationResponse;
import networkrespnse.Response;
import networkrespnse.SQLResponse;
import networkrespnse.ServerErrorResponse;
import networkrespnse.SettingsXML;
import networkrespnse.SignPreliminaryOrderAnswer;
import networkrespnse.SrvMessageResponse;
import networkrespnse.TCPMessageResponse;
import networkrespnse.TaxiParkingStatisticResponse;
import networkrespnse.TaxiParkingsLastChangeDateResponse;
import networkrespnse.TaxiParkingsResponse;
import networkrespnse.TaxiParkingsResponse2;
import networkrespnse.UnRegisterOnTaxiParkingResponse;
import networkrespnse.WorkReportResponse;


public class ParameterDecoder
{
    byte[] buff4;
    
    public ParameterDecoder()
    {
        buff4 = new byte[4];
    }

    public Response parseResponse(byte[] data)
    {
        //Определяем номер пакета
        int packetNumber = -1;
        if (data.length > 4)
        {
            System.arraycopy(data, data.length - 4, buff4, 0, buff4.length);
            packetNumber = Utils.byteToInt(buff4);
        }
        
        ResponseDescription responseDescription;
        try
        {
            responseDescription = getResponseCode(data);
        }
        catch(Exception ex){
            return new ParseError();
        }

        if (responseDescription.getResponseCode() == Response.SRV_TRANSFERDATA_RESPONSE)
        try
        {
            responseDescription = getTransferCode(data);
        }
        catch(Exception ex) {
            return new ParseError();
        }

        Response result;
        try
        {
            result = getResponse(responseDescription, data);
        }
        catch(Exception ex){
            return new ParseError();
        }
        
        if (result != null)
        {
            result.setPacketNumber(packetNumber);
        }
        
        return result;
    }

	public ResponseDescription getResponseCode(byte[] data)//������� ����������� �� ����� ������ ������ �����
	{
            int res;
            int nameSize;
            String className;
            byte[] temp;
            //���������� ������ ������
            temp = new byte[4];
            for (int i=0;i<4;i++)
            {
                temp[i] = data[i];
            }
            nameSize = Utils.byteToInt(temp);
            //�������� ���� ������
            temp = new byte[nameSize];
            for (int i=0;i<nameSize;i++)
            {
                    temp[i] = data[i+4];
            }	
            className = new String(temp);
            //���������� �� �������� ������ ��� ������
            res = selectCode(className);
            return new ResponseDescription(res, className);
	}
	
        private class ResponseDescription
        {
            private int responseCode;
            private String className;
            public ResponseDescription(int responseCode, String className)
            {
                this.responseCode = responseCode;
                this.className = className;
            }

            public String getClassName() 
            {
                return className;
            }

            public int getResponseCode() 
            {
                return responseCode;
            }     
        }
        
	private int selectCode(String val)//������� ���������� ��� ������
	{
//System.out.println("[" + val + "]");
		if (val.equals("IMAP.Net.SrvTransfereError"))
		{
			return Response.SERVER_ERROR_RESPONSE;
		}
                if (val.equals("IMAP.Net.SrvLoginAnswer"))
		{
			return Response.LOGIN_RESPONSE;
		}
		if (val.equals("IMAP.Net.SrvPing"))
		{
			return Response.PING_RESPONSE;
		}
		if (val.equals("IMAP.Net.SrvMessage"))
		{
			return Response.SRV_MESSAGE_RESPONSE;
		}
		if (val.equals("IMAP.Net.SrvTransfereData"))
		{
			return Response.SRV_TRANSFERDATA_RESPONSE;
		}
		if (val.equals("IMAP.Net.RegisterOnTaxiParking_answer"))
		{
			return Response.REGISTER_ON_TAXI_PARKING_RESPONSE;
		}
		if (val.equals("IMAP.Net.RelayCommunication"))
		{
			return Response.RELAY_COMMUNICATION_RESPONSE;
		}
		if (val.equals("IMAP.Net.DispOrder")){
                    return Response.ORDER_RESPONSE;
		}
                if (val.equals("IMAP.Net.DispOrder2")) {
                    return Response.ORDER_RESPONSE2;
                }
                if (val.equals("IMAP.Net.DispOrder3")) {
                    return Response.ORDER_RESPONSE3;
                }
                if (val.equals("IMAP.Net.DispOrder4")) {
                    return Response.ORDER_RESPONSE4;
                }
		if (val.equals("IMAP.Net.TCPMessage"))
		{
			return Response.TCPMESSAGE_RESPONSE;
		}
		if (val.equals("IMAP.Net.RequestConfirmation"))
		{
			return Response.REQUEST_CONFIRMATION_RESPONSE;
		}
		if (val.equals("IMAP.Net.GetTaxiParkingStatistic_answer"))
		{
			return Response.TAXI_PARKING_STATISTIC_RESPONSE;
		}
		if (val.equals("IMAP.Net.GetTaxiParkingsLastChangeDate_answer"))
		{
			return Response.TAXI_PARKING_LAST_CHANGE_DATE_RESPONSE;
		}
		if (val.equals("IMAP.Net.GetWorkReport_answer"))
		{
			return Response.WORK_REPORT_RESPONSE;
		}
		if (val.equals("IMAP.Net.GetTaxiParkings_answer"))
		{
			return Response.TAXI_PARKINGS_RESPONSE;
		}
                if (val.equals("IMAP.Net.GetTaxiParkings_answer2"))
                {
                    return Response.TAXI_PARKINGS_RESPONSE2;
                }
		if (val.equals("IMAP.Net.UnRegisterOnTaxiParking_answer"))
		{
			return Response.UNREGISTER_ON_TAXI_PARKING_RESPONSE;
		}
		if (val.equals("IMAP.Net.GetDriverParkingPosition_answer"))
		{
			return Response.DRIVER_PARKING_POSITION_RESPONSE;
		}
		if (val.equals("IMAP.Net.PPCSettings"))
		{
			return Response.PPCSETTINGS_RESPONSE;
		}
                if (val.equals("IMAP.Net.SettingXml")) {
                    return Response.SETTINGSXML_RESPONSE;
                }
		if (val.equals("IMAP.Net.CallSignChanged"))
		{
			return Response.CALL_SIGNCHANGED_RESPONSE;
		}
                if (val.equals("IMAP.Net.GetOrders_answer") || val.equals("IMAP.Net.InnerNamespace.GetOrders_answer"))
                {
                    return Response.GET_ORDERS_RESPONSE;
                }
                if (val.equals("IMAP.Net.ExequteQuerryCommand_answer"))
                {
                    return Response.SQL_RESPONSE;
                }
                if (val.equals("IMAP.Net.GetPreliminaryOrders_answer"))
                {
                    return Response.PREORDERS_RESPONSE;
                }
                if (val.equals("IMAP.Net.GetCSBalanceAnswer"))
                {
                    return Response.CSBALANCE_RESPONSE;
                }
                if (val.equals("IMAP.Net.DriverMessage"))
                {
                    return Response.DRIVER_MESSAGE_RESPONSE;
                }
                if (val.equals("IMAP.Net.SearchInEtherOrderOver"))
                {
                    return Response.CANCEL_EFIR_ORDER;
                }
                if (val.equals("IMAP.Net.RemoveOrdersInEther"))
                {
                    return Response.CLEAR_EFIR;
                }
                if (val.equals("IMAP.Net.PPSChangeState")) {
                    return Response.CHANGE_STATE;
                }
//                if (val.equals("IMAP.Net.SignPreliminaryOrder_answer")) {
//                    return Response.SIGN_PRELIMINARY_ORDER_ANSWER;
//                }
//                if (val.equals("IMAP.Net.RefusePreliminaryOrder_answer")) {
//                    return Response.REFUSE_PRELIMINARY_ORDER_ANSWER;
//                }
		return Response.UNKNOWN_RESPONSE;
	}
	
	private ResponseDescription getTransferCode(byte[] data)//��������� ����� ������ �� ������ SrvTransfereData
	{
		byte[] body,temp;
		int size,offset;
		//��������  body
		body = getTransferBody(data);
		//�������� ������ ����� ������
		temp = new byte[4];
		offset = 0;
		for (int i=0;i<4;i++)
		{
			temp[i] = body[offset++];
		}
		size = Utils.byteToInt(temp);
		//�������� ��� ������
		temp = new byte[size];
		for (int i=0;i<size;i++)
		{
			temp[i] = body[offset++];
		}
		String className = new String(temp);
		
		return new ResponseDescription(selectCode(className), className);
	}
	
	public static byte[] getTransferBody(byte[] data)//��������� ���� Body �� ������ SrvTransfereData
	{
		byte[] res,temp;
		int offset,size;
		offset = 0;
		temp = new byte[4];
		//��� ������
		for (int i=0;i<4;i++)
		{
			temp[i] = data[offset++];
		}
		size = Utils.byteToInt(temp);
		offset += size;
		//��� �����������
		for (int i=0;i<4;i++)
		{
			temp[i] = data[offset++];
		}
		size = Utils.byteToInt(temp);
		offset += size;
		//��������� ������
		offset += 4 + 4 + 16 + 1;
		//������ ���� Body
		for (int i=0;i<4;i++)
		{
			temp[i] = data[offset++];
		}
		size = Utils.byteToInt(temp);
		//���� Body
		res = new byte[size];
		for (int i=0;i<res.length;i++)
		{
			res[i] = data[offset++];
		}
		return res;
	}

        private Response getResponse(ResponseDescription responseDescription, byte[] data)
        {
            switch (responseDescription.getResponseCode())
            {
                case Response.SERVER_ERROR_RESPONSE : return new ServerErrorResponse();
		case Response.LOGIN_RESPONSE : return new LoginResponse(data);
		case Response.PING_RESPONSE : return new PingResponse();
		case Response.SRV_MESSAGE_RESPONSE : return new SrvMessageResponse(data);
		case Response.SRV_TRANSFERDATA_RESPONSE : return null;
		case Response.REGISTER_ON_TAXI_PARKING_RESPONSE : return new RegisterOnTaxiParkingResponse(data);
		case Response.RELAY_COMMUNICATION_RESPONSE : return new RelayCommunicationResponse(data);
		case Response.ORDER_RESPONSE : return new OrderResponse(data);
                case Response.ORDER_RESPONSE2 : return new OrderResponse2(data);
                case Response.ORDER_RESPONSE3 : return new OrderResponse3(data);
                case Response.ORDER_RESPONSE4 : return new OrderResponse4(data);
		case Response.TCPMESSAGE_RESPONSE : return new TCPMessageResponse(data);
		case Response.REQUEST_CONFIRMATION_RESPONSE : return new RequestConfirmationResponse();
		case Response.TAXI_PARKING_STATISTIC_RESPONSE : return new TaxiParkingStatisticResponse(data);
		case Response.TAXI_PARKING_LAST_CHANGE_DATE_RESPONSE : return new TaxiParkingsLastChangeDateResponse(data);
		case Response.WORK_REPORT_RESPONSE : return new WorkReportResponse(data);
		case Response.TAXI_PARKINGS_RESPONSE : return new TaxiParkingsResponse(data);
                case Response.TAXI_PARKINGS_RESPONSE2 : return new TaxiParkingsResponse2(data);
		case Response.UNREGISTER_ON_TAXI_PARKING_RESPONSE : return new UnRegisterOnTaxiParkingResponse(data);
		case Response.DRIVER_PARKING_POSITION_RESPONSE : return new DriverParkingPositionResponse(data);
		case Response.PPCSETTINGS_RESPONSE : return new PPCSettingsResponse(data);
		case Response.CALL_SIGNCHANGED_RESPONSE : return new CallSignChangedResponse(data);
                case Response.GET_ORDERS_RESPONSE : return new GetOrdersResponse(data);
                case Response.SQL_RESPONSE : return new SQLResponse(data);
                case Response.PREORDERS_RESPONSE : return new PreOrdersResponse(data);
                case Response.CSBALANCE_RESPONSE : return new GetCSBalanceAnswer(data);
                case Response.DRIVER_MESSAGE_RESPONSE : return new DriverMessageResponse(data); 
                case Response.CANCEL_EFIR_ORDER : return new CancelEfirOrder(data);
                case Response.CLEAR_EFIR : return new ClearEfir(data);
                case Response.CHANGE_STATE : return new ChangeState(data); 
                case Response.SIGN_PRELIMINARY_ORDER_ANSWER : return new SignPreliminaryOrderAnswer(data);
                case Response.REFUSE_PRELIMINARY_ORDER_ANSWER : return new RefusePreliminaryOrderAnswer(data);
                case Response.SETTINGSXML_RESPONSE : return new SettingsXML(data);
                default: return null;
            }
        }	
}
